package com.example.springboot.controller;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.example.springboot.Exception.ServiceException;
import com.example.springboot.common.AuthAccess;
import com.example.springboot.common.OBJ;
import com.example.springboot.common.Result;
import com.example.springboot.service.impl.*;
import com.example.springboot.utils.DateUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 功能：实现登录、注册、忘记密码功能

 * 日期：2024/1/9 9:54
 */

@RestController
public class WebController {


    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private StoreServiceImpl storeService;
    @Autowired
    private AdminServiceImpl adminService;
    @Autowired
    private OrdersServiceImpl ordersService;
    @Autowired
    private ProductServiceImpl productService;
    @Autowired
    private CategoryServiceImpl categoryService;
    @Autowired
    private OrdersProductServiceImpl ordersProductService;
    @Autowired
    private UserFavoriteProductServiceImpl userFavoriteProductService;


    /**
     * 账号登录
     *
     * @param account
     * @return
     */
    @AuthAccess
    @PostMapping("/login")
    public Result login(@RequestBody Account account) {
        // 尽管前端已经校验了用户输入的账号、密码、验证码
        // 但是为了安全性，防止黑客通过抓包工具获取账号、密码，
        // 这里我们依然需要对账号、密码进行校验
        // 只是简单地判断账号和密码是否为空
        if (StrUtil.isBlank(account.getUsername()) || StrUtil.isBlank(account.getPassword())) {
            return Result.error("401", "账号或密码不能为空");
        }
        // 实现不同用户登录
        // 获取用户登录的角色，调用不同的角色数据库，以此来实现返回不同的数据
        if (account.getRole().equals("用户")) {
            return Result.success(userService.login(account));
        } else if (account.getRole().equals("商家")) {
            return Result.success(storeService.login(account));
        } else if (account.getRole().equals("管理员")) {
            return Result.success(adminService.login(account));
        } else {
            return Result.error("401", "角色不存在");
        }
    }


    /**
     * 注册账号
     *
     * @param account
     * @return
     */
    @AuthAccess
    @PostMapping("/register")
    public Result register(@RequestBody Account account) {
        // 简单地判断账号、密码和邮箱是否为空
        if (StrUtil.isBlank(account.getUsername()) || StrUtil.isBlank(account.getPassword()) || StrUtil.isBlank(account.getEmail())) {
            return Result.error("422", "账号、密码和邮箱不能为空");
        }
        // 判断用户名长度是都大于等于4、密码长度是否大于等于6、邮箱是否合法
        if (account.getUsername().length() < 4 || account.getPassword().length() < 6 || !Validator.isEmail(account.getEmail())) {
            return Result.error("422", "账号、密码和邮箱格式不正确");
        }

        // 实现不同用户注册
        // 获取用户注册的角色，调用不同的角色数据库，以此来实现返回不同的数据
        if (account.getRole().equals("用户")) {
            return Result.success(userService.register(account));
        } else if (account.getRole().equals("商家")) {
            return Result.success(storeService.register(account));
        } else if (account.getRole().equals("管理员")) {
            return Result.success(adminService.register(account));
        } else {
            return Result.error("422", "角色不存在！");
        }
    }


    /**
     * 找回密码
     *
     * @param account
     * @return
     */
    @AuthAccess
    @PostMapping("/findPassword")
    public Result findPassword(@RequestBody Account account) {
        // 简单地判断账号、密码和邮箱是否为空
        if (StrUtil.isBlank(account.getUsername())) {
            return Result.error("423", "账号不能为空");
        }
        // 判断用户名长度是都大于等于4、密码长度是否大于等于6、邮箱是否合法
        if (account.getUsername().length() < 4) {
            return Result.error("423", "账号不正确");
        }

        // 实现不同用户找回密码
        // 获取用户注册的角色，调用不同的角色数据库，以此来实现返回不同的数据
        if (account.getRole().equals("用户")) {
            userService.findPassword(account);
            return Result.success("密码重置成功，请登录！");
        } else if (account.getRole().equals("商家")) {
            storeService.findPassword(account);
            return Result.success("密码重置成功，请登录！");
        } else if (account.getRole().equals("管理员")) {
            adminService.findPassword(account);
            return Result.success("密码重置成功，请登录！");
        } else {
            return Result.error("423", "角色不存在！");
        }
    }

    /**
     * 检查Token
     *
     * @param account
     * @return
     */
    @AuthAccess
    @PostMapping("/checkToken")
    public Result checkToken(@RequestBody Account account) {

        // 获取参数判断
        if (account == null) {
            return Result.error("401", "account为空");
        }
        // 获取token
        String token = account.getToken();
        // 判断token是否为空
        if (StrUtil.isBlank(token)) {
            return Result.error("401", "token为空");
        }
        // 检测token是否过期
        // 用户密码加签验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(account.getPassword())).build();
        try {
            jwtVerifier.verify(token); // 验证token
        } catch (JWTVerificationException e) {
            throw new ServiceException("401", "token过期或无效");
        }
        return Result.success("token验证通过");
    }


    /**
     * 查询天气
     * <p>
     * https://www.juhe.cn/box/index/id/73
     *
     * @param city
     * @return
     */
    @AuthAccess
    @GetMapping("/weather")
    public Result queryWeather(@RequestParam String city) {

        if (StrUtil.isBlank(city)) {
            return Result.error("488", "天气城市不能为空");
        }

        String apiUrl = "http://apis.juhe.cn/simpleWeather/query";
        String key = "56aed701f012b2f45e3e26208077ff91";

        String queryUrl = apiUrl + "?city=" + city + "&key=" + key;

        try {
            // 创建URL对象
            URL url = new URL(queryUrl);

            // 创建HttpURLConnection对象
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法为GET
            connection.setRequestMethod("GET");

            // 获取响应代码
            int responseCode = connection.getResponseCode();

            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 读取响应内容
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                StringBuilder response = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();

                // 解析JSON数据
                // 这里你可以根据需要使用JSON库进行解析，比如使用Gson或Jackson等

//                System.out.println(response.toString());

                String json = response.toString();
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, Object> data = objectMapper.readValue(json, Map.class);
                Map<String, Object> result = (Map<String, Object>) data.get("result");
                Map<String, Object> realtime = (Map<String, Object>) result.get("realtime");

                String weather = realtime.get("info").toString();
                String temperature = realtime.get("temperature").toString();
                String windDirection = realtime.get("direct").toString();
                String windPower = realtime.get("power").toString();

                String weatherInfo = city + "  " + weather + "  " + temperature + "℃ " + "风向：" + windDirection + " " + windPower;
                return Result.success(weatherInfo);

            } else {
                System.out.println("请求失败，响应代码：" + responseCode);
            }

            // 关闭连接
            connection.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("请求天气预报API失败");
        }
        return Result.error("请求天气预报API失败");
    }


    /**
     * 获取星座运势
     *
     * @param consName
     * @param type
     * @return
     */
    @AuthAccess
    @GetMapping("/constellation")
    public Result queryConstellation(@RequestParam String consName, @RequestParam String type) {


        if (StrUtil.isBlank(consName)) {
            return Result.error("488", "星座名称不能为空");
        }

        if (StrUtil.isBlank(type)) {
            return Result.error("488", "类型参数不能为空");
        }

        String key = "9531ca6e4b858c860494252eae2ab54c";

        String result = "";
        String urlStr = "http://web.juhe.cn/constellation/getAll" + "?consName=" + URLEncoder.encode(consName) + "&type=" + type + "&key=" + key;
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
                String response = "";
                String line;
                while ((line = in.readLine()) != null) {
                    response += line;
                }
                in.close();

                JSONObject jsonObject = new JSONObject(response);
                // 获取其中的一个key
//                result = jsonObject.getStr("summary");
                return Result.success(jsonObject);
            } else {
                throw new RuntimeException("请求星座API失败");
            }
        } catch (Exception e) {
            throw new RuntimeException("请求星座API失败");
        }
    }


    /**
     * 获取财经头条
     *
     * @return
     */
    @AuthAccess
    @GetMapping("/toutiao")
    public Result queryToutiao() {
        String key = "041bc881227bdf42473505ca3674a5a2";

        String urlStr = "http://v.juhe.cn/toutiao/index" + "?type=caijing" + "&page=&page_size=&is_filter=" + "&key=" + key;

        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            int responseCode = conn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();

                String json = response.toString();
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, Object> data = objectMapper.readValue(json, Map.class);
                Map<String, Object> result = (Map<String, Object>) data.get("result");
                return Result.success(result);
            } else {
                throw new RuntimeException("请求财经头条API失败");
            }
        } catch (Exception e) {
            throw new RuntimeException("请求财经头条API失败");
        }
    }


    /**
     * 折线统计图
     *
     * @return
     */
    @AuthAccess
    @GetMapping("/lineCharts")
    public Result lineCharts() {
        // 尝试获取订单服务
        try {
            // 获取

            // 获取最近一周内的所有订单
            List<Orders> list = ordersService.selectRecentWeek();
            // 获取订单创建时间
//            Set<Date> datesTemp = list.stream().map(Orders::getCreateTime).collect(Collectors.toSet());
//            Set<String> dates = new HashSet<>();
//            for (Date date : datesTemp) {
//                dates.add(DateUtil.getStringDateSimple(date));
//            }
            // 将Set转换为List
//            List<String> dateList = CollUtil.newArrayList(dates);

            List<String> dateList = DateUtil.getRecentDaysAsString(7);
            // 对日期进行排序
            dateList.sort(Comparator.naturalOrder());
            // 创建折线列表
            List<Dict> lineList = new ArrayList<>();
            // 遍历日期列表
            for (String date : dateList) {
                // 计算每天订单的金额总和
                BigDecimal price = list.
                        stream().
                        filter(orders -> DateUtil.getStringDateSimple(orders.getCreateTime()).equals(date)).
                        map(Orders::getPayment).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                // 计算每天订单的数量
                Long count = list.
                        stream().
                        filter(orders -> DateUtil.getStringDateSimple(orders.getCreateTime()).equals(date))
                        .count();

                // 计算每天订单的用户数量
                Integer userCount = list.stream()
                        .filter(orders -> DateUtil.getStringDateSimple(orders.getCreateTime()).equals(date))
                        .map(Orders::getUserId).
                        collect(Collectors.toSet()).size();
                // 计算每天订单的商家数量
                Integer storeCount = list.stream()
                        .filter(orders -> DateUtil.getStringDateSimple(orders.getCreateTime()).equals(date))
                        .map(Orders::getStoreId).
                        collect(Collectors.toSet()).size();
                // 创建字典
                Dict dict = Dict.create();
                // 将日期和金额总和放入字典
                Dict line = dict.set("date", date)
                        .set("price", price)
                        .set("count", count)
                        .set("userCount", userCount)
                        .set("storeCount", storeCount);
                // 将字典添加到折线列表
                lineList.add(line);
            }
            // 返回折线统计图数据
            return Result.success(lineList);
        } catch (Exception e) {
            throw new RuntimeException("请求折线统计图数据失败");
        }
    }


    /**
     * 折线统计图
     *
     * @return
     */
    @AuthAccess
    @GetMapping("/productCharts")
    public Result productCharts() {
        // 尝试获取订单服务
        try {
            // 获取TOP20的商品集合
            List<Product> list = productService.selectTop10CategoryAdmin();

            // 创建折线列表
            List<Dict> lineList = new ArrayList<>();

            // 在UserFavoriteProductService获取这个商品的收藏量
            for (Product product : list) {
                product.setFavoriteCount(userFavoriteProductService.getFavoriteCount(product.getId()));
                // 创建字典
                Dict dict = Dict.create();
                // 将日期和金额总和放入字典
                Dict line = dict.set("productName", product.getName())
                        .set("sales", product.getSales())
                        .set("views", product.getViews())
                        .set("favoriteCount", product.getFavoriteCount());
                // 将字典添加到折线列表
                lineList.add(line);
            }
            // 返回折线统计图数据
            return Result.success(lineList);
        } catch (Exception e) {
            throw new RuntimeException("请求折线统计图数据失败");
        }
    }


    /**
     * 柱状图
     * <p>
     * <p>
     * 展示前五商品分类的商品数量和订单数量
     *
     * @return
     */
    @AuthAccess
    @GetMapping("/barCharts")
    public Result barCharts() {
        List<Category> list = new ArrayList<>();

        // 柱状图数据
        try {
            // 获取前五的商品分类
            list = categoryService.selectTop5Category();
        } catch (Exception e) {
            throw new RuntimeException("请求柱状图数据失败");
        }
        List<Dict> barList = new ArrayList<>();
        for (Category category : list) {

            Dict dict = Dict.create();
            Dict bar = dict.set("name", category.getName())
                    .set("productCount", category.getProductCount())
                    .set("orderCount", category.getOrderCount());
            barList.add(bar);
        }
        return Result.success(barList);
    }


    /**
     * 下面都是测试方法
     */

    @RequestMapping("/main")

    public Result sayHello() {
        return Result.success("hello world");
    }

    @PostMapping("/post")
    public Result post(@RequestBody OBJ obj) {
        System.out.println(obj == null ? "" : obj.toString());
        return Result.success(obj == null ? "暂无此数据" : obj);
    }

    @PutMapping("/put")
    public Result put(@RequestBody OBJ obj) {
        System.out.println(obj == null ? "" : obj.toString());
        return Result.success(obj == null ? "暂无此数据" : obj);
    }

    /**
     * 删除一个
     *
     * @param id
     * @return
     */
    @DeleteMapping("/delete/{id}")
    public Result delete(@PathVariable String id) {
        System.out.println(id);
        return Result.success(id);
    }

    @DeleteMapping("/delete")
    public Result deleteList(@RequestBody List<Integer> ids) {
        return Result.success(ids);
    }


}
